package juc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class NotifyWait {
    
    /*
     * 生产者-消费者模式
     * 两个线程, 操作初始值为 0 的变量, 一个线程对变量加 1, 一个线程对变量减 1, 交替 10 轮
     */
    public static void main(String[] args) {
         ShareData sd = new ShareData();
         
         // 生产者
         new Thread(() -> {
             for(int i=0; i<10; i++) {
                 try {
                    sd.increament();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
             }
         }, "A").start();
         
         // 消费者
         new Thread(() -> {
             for(int i=0; i<10; i++) {
                 try {
                    sd.decreament();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
             }
         }, "B").start();
    }
}

class ShareData {
    private Integer num = 0;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    
    public void increament() throws InterruptedException {
        lock.lock();
        try {
            // 判断, 多线程中的判断只能用循环, 以防止虚假唤醒
            while(num.equals(1)) {
                condition.await();
            }
            // 操作
            num++;
            System.out.println(Thread.currentThread().getName() + "执行了加 1");
            // 通知
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
    
    public void decreament() throws InterruptedException {
        // 替代了 synchronized
        lock.lock();
        try {
            while(num.equals(0)) {
                // 替代 this.wait();
                condition.await();
            }
            num--;
            System.out.println(Thread.currentThread().getName() + "执行了减 1");
            // 替代 this.notifyAll();
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
}